package melody

import (
	"net/http"

	"github.com/gorilla/websocket"
)

const (
	CloseNormalClosure           = 1000
	CloseGoingAway               = 1001
	CloseProtocolError           = 1002
	CloseUnsupportedData         = 1003
	CloseNoStatusReceived        = 1005
	CloseAbnormalClosure         = 1006
	CloseInvalidFramePayloadData = 1007
	ClosePolicyViolation         = 1008
	CloseMessageTooBig           = 1009
	CloseMandatoryExtension      = 1010
	CloseInternalServerErr       = 1011
	CloseServiceRestart          = 1012
	CloseTryAgainLater           = 1013
	CloseTLSHandshake            = 1015
)

type WSServer interface {
	HandlerMessage(interface{}, []byte)
	HandlerSend(interface{}, []byte)
	Error(interface{}, error)
	Close(interface{}, int, string) error
	Connect(s *Session)
	DisConnect(ss interface{})
	HandlerPong(interface{})
}
type Melody struct {
	Config   *Config
	Upgrader *websocket.Upgrader
	WS       WSServer
}

func New() *Melody {
	upgrader := &websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		CheckOrigin:     func(r *http.Request) bool { return true },
	}
	return &Melody{
		Config:   newConfig(),
		Upgrader: upgrader,
	}
}
func (m *Melody) RegisterHandler(s WSServer) {
	m.WS = s
}
func (m *Melody) Connect(w http.ResponseWriter, r *http.Request) (*Session, error) {
	return m.HandleRequestWithKeys(w, r, nil)
}
func (m *Melody) HandleRequestWithKeys(w http.ResponseWriter, r *http.Request, keys map[string]interface{}) (*Session, error) {
	conn, err := m.Upgrader.Upgrade(w, r, w.Header())
	if err != nil {
		return nil, err
	}
	s := &Session{
		conn:       conn,
		melody:     m,
		output:     make(chan *envelope, m.Config.MessageBufferSize),
		outputDone: make(chan struct{}),
		open:       true,
	}
	m.WS.Connect(s)
	return s, nil
}
func (m *Melody) Server(ss interface{}, session *Session) error {
	session.registerimpl(ss)
	go session.writePump()
	session.readPump()
	session.close()
	m.WS.DisConnect(ss)
	return nil
}
